package com.stlm2.dems.service;

import com.stlm2.core.base.BaseDao;
import com.stlm2.core.base.impl.BaseServiceImpl;
import com.stlm2.dataSource.DBContextHolder;
import com.stlm2.dems.dao.*;
import com.stlm2.dems.entity.*;
import com.stlm2.dems.user.dao.AccountDao;
import com.stlm2.dems.user.entity.Account;
import com.stlm2.dems.user.entity.UserState;
import com.stlm2.dems.util.CoreLogic;
import com.stlm2.util.PushUtil;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

@Service("goodsOrderService")
@Transactional(rollbackForClassName = {"java.lang.Exception"}, propagation = Propagation.REQUIRED)
public class GoodsOrderService extends BaseServiceImpl<GoodsOrder> {

    @Resource
    private PurchaseOrderDao purchaseOrderDao;
    @Resource
    private CoreLogic coreLogic;
    @Resource
    private ShopOrderDao shopOrderDao;
    @Resource
    private GoodsOrderDao goodsOrderDao;
    @Resource
    private GoodsValueAddedServicesDao goodsValueAddedServicesDao;
    @Resource
    private ServiceOrderDao serviceOrderDao;
    @Resource
    private InventoryDao inventoryDao;
    @Resource
    private InventoryLogDao inventoryLogDao;
    @Resource
    private ConfigDao configDao;
    @Resource
    private UserDao userDao;
    @Resource
    private CommissionDao commissionDao;
    @Resource
    private AccountDao accountDao;
    @Resource
    private FmsFlowDao fmsFlowDao;
    @Resource
    private DdmGoodsDao ddmGoodsDao;
    @Resource
    private DdmShopDao ddmShopDao;

    @Override
    protected BaseDao<GoodsOrder> getDao() {
        return goodsOrderDao;
    }


    /**
     * 订单支付
     *
     * @param temp
     */
    public PurchaseOrder pay(PurchaseOrder temp, PayChannel payChannel, String tno,String companyCode) {


        if (temp == null || payChannel == null)
            throw new RuntimeException("订单或者支付方式不能为空！");
        PurchaseOrder purchaseOrder = purchaseOrderDao.getByIdForUpdate(temp.getId());//数据库加悲观锁，防止重复支付

        synchronized (purchaseOrder) {
            if (!OrderState.Create.equals(purchaseOrder.getOrderState()))
                return purchaseOrder;

            if (PayChannel.Balance.equals(payChannel)) {
                boolean payResult = coreLogic.changeMoneyAccount(temp.getUserId(), temp.getPayMoney(), FlowSource.Buy, FlowType.Reduce);
                if (!payResult) {
                    throw new RuntimeException("余额支付失败！");
                }
            } else {
                if (StringUtils.isBlank(tno))
                    return null;
            }

            //修改一级订单
            purchaseOrder.setPayChannel(payChannel);
            purchaseOrder.setTransactionNo(tno);
            purchaseOrder.setPayTime(new Date());
            purchaseOrder.setOrderState(OrderState.Payment);
            purchaseOrder.setPayType(PayType.OnLine);
            purchaseOrderDao.modify(purchaseOrder);

            //修改二级订单状态
            ShopOrder shopOrderParam = new ShopOrder();
            shopOrderParam.setPurchaseOrderCode(purchaseOrder.getCode());
            List<ShopOrder> shopOrders = shopOrderDao.queryList(-1, -1, shopOrderParam);
            if (shopOrders != null && shopOrders.size() > 0) {
                for (ShopOrder shopOrder : shopOrders) {
                    if (!OrderState.Create.equals(shopOrder.getOrderState()))
                        continue;

                    shopOrder.setOrderState(OrderState.Payment);
                    shopOrder.setPayTime(purchaseOrder.getPayTime());
                    shopOrderDao.modify(shopOrder);

                    //修改三级订单状态
                    GoodsOrder goodsOrderParam = new GoodsOrder();
                    goodsOrderParam.setShopOrderCode(shopOrder.getCode());
                    goodsOrderParam.setOrderState(OrderState.Create);
                    List<GoodsOrder> goodsOrderList = goodsOrderDao.queryList(-1, -1, goodsOrderParam);

                    if (goodsOrderList != null && goodsOrderList.size() > 0) {
                        for (GoodsOrder goodsOrder : goodsOrderList) {
                            if (!OrderState.Create.equals(goodsOrder.getOrderState()))
                                continue;

                            //增加服务
                            if (goodsOrder.getAddServiceId() != null) {
                                GoodsOrder addService = this.addService(goodsOrder, shopOrder);
                                if (addService == null)
                                    throw new RuntimeException("添加服务失败！");
                            }
                            //减少库存
                            GoodsOrder addInventory=this.addInventory(goodsOrder,shopOrder);
                            if(addInventory==null)
                                throw new RuntimeException("减少库存失败！");


                            if(!addSalesVolume(goodsOrder))
                                throw new RuntimeException("增加销量失败！");

                            goodsOrder.setOrderState(OrderState.Payment);
                            goodsOrder.setPayTime(purchaseOrder.getPayTime());
                            goodsOrderDao.modify(goodsOrder);



                        }
                    }
                }
            }
            coreLogic.addFundsFlow(purchaseOrder.getUserId(), purchaseOrder.getPayMoney(), FlowSource.Buy, FlowType.Reduce, purchaseOrder.getId(), purchaseOrder.getCode());
            DdmShop ddmShop=ddmShopDao.getById(shopOrders.get(0).getShopId());
            if(!org.springframework.util.StringUtils.isEmpty(ddmShop.getContact())){
                PushUtil.sendAlias("您有一笔交易订单！",ddmShop.getContact(),null,companyCode);
            }

        }
        return purchaseOrder;
    }

    public GoodsOrder addService(GoodsOrder goodsOrder, ShopOrder shopOrder) {
        String[] serviceIds = goodsOrder.getAddServiceId().split(",");
        for (String serviceId : serviceIds) {
            //添加服务
            GoodsValueAddedServices goodsValueAddedServices = goodsValueAddedServicesDao.getByGoodsIdAndServiceId(goodsOrder.getGoodsId(),Integer.parseInt(serviceId));
            if (goodsValueAddedServices != null) {
                int period = goodsValueAddedServices.getWarrantyPeriod();
                ServiceOrder serviceOrder = new ServiceOrder();
                serviceOrder.setUserId(goodsOrder.getUserId());
                serviceOrder.setCreateTime(new Date());
                serviceOrder.setGoodsOrderCode(goodsOrder.getCode());
                serviceOrder.setNum(1);
                serviceOrder.setServiceId(goodsValueAddedServices.getValueAddedServicesId());
                serviceOrder.setShopOrderCode(shopOrder.getCode());
                serviceOrder.setPurchaseOrderCode(goodsOrder.getPurchaseOrderCode());
                serviceOrder.setState(true);
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(new Date());
                calendar.add(Calendar.MONTH, period);
                serviceOrder.setEndTime(calendar.getTime());

                serviceOrderDao.add(serviceOrder);
            }else
                return null;
        }
        return goodsOrder;
    }

    public GoodsOrder addInventory(GoodsOrder goodsOrder, ShopOrder shopOrder) {

        //减去库存
        Inventory inventory = inventoryDao.getOnlyInventory(shopOrder.getShopId(), goodsOrder.getGoodsId(), goodsOrder.getGoodsSpecificationId());
        if (inventory != null) {
            inventory.setInventory(inventory.getInventory() - goodsOrder.getNum());
            inventory.setUpdateUserId(goodsOrder.getUserId());
            inventory.setUpdateTime(new Date());
            inventoryDao.modify(inventory);

            InventoryLog inventoryLog = new InventoryLog();
            inventoryLog.setInventoryId(inventory.getId());
            inventoryLog.setUserId(goodsOrder.getUserId());
            inventoryLog.setType(FlowType.Reduce);
            inventoryLog.setInventorySource(InventorySource.PurchaseOrder);
            inventoryLog.setChangeNum(goodsOrder.getNum());
            inventoryLog.setCode(goodsOrder.getCode());
            inventoryLog.setCreateTime(new Date());
            inventoryLog.setRemark("商品购买减库存");
            inventoryLogDao.add(inventoryLog);
        }else
            return null;
        return goodsOrder;
    }

    public Boolean addSalesVolume(GoodsOrder goodsOrder) {

        //增加销量
        DdmGoods goods=ddmGoodsDao.getById(goodsOrder.getGoodsId());
        if(goods!=null){
            goods.setSalesVolume(goods.getSalesVolume()+goodsOrder.getNum());
            ddmGoodsDao.modify(goods);
        }else {
            return false;
        }

        return true;
    }


    //定时任务  分佣 分享经济
    public void finishOrder() {
        GoodsOrder param = new GoodsOrder();
        // 确认收货时间设置为前十五天和前十四天之间的天数
        param.setReceiptTime(DateUtils.addDays(new Date(), -15));
        param.setOrderState(OrderState.Receipt);
        List<GoodsOrder> goodsOrderList = goodsOrderDao.queryList(-1, Integer.MAX_VALUE, param);
        if (goodsOrderList!=null&&goodsOrderList.size() > 0) {
            System.out.println("处理分佣的订单个数" + goodsOrderList.size());


            //一级推广佣金比例
            Config config3 = new Config();
            config3.setConfigName("FIRST_LEVEL_RATE");
            Config config4 = configDao.selectOneFromRedis(config3);
            if (config4 == null) {
                System.out.println("redis中获取FIRST_LEVEL_RATE对象失败，尝试从数据库中获取");
                config4 = configDao.getByName("FIRST_LEVEL_RATE");
                if (config4 == null) {
                    System.out.println("数据中获取FIRST_LEVEL_RATE对象失败");
                    return;
                }
            }
            BigDecimal firstLevelRate = new BigDecimal(config4.getConfigValue());
            //二级推广佣金比例
            Config config5 = new Config();
            config5.setConfigName("SECOND_LEVEL_RATE");
            Config config6 = configDao.selectOneFromRedis(config5);
            if (config6 == null) {
                System.out.println("redis中获取SECOND_LEVEL_RATE对象失败，尝试从数据库中获取");
                config6 = configDao.getByName("SECOND_LEVEL_RATE");
                if (config6 == null) {
                    System.out.println("数据库中获取SECOND_LEVEL_RATE对象失败");
                    return;
                }
            }
            BigDecimal secondLevelRate = new BigDecimal(config6.getConfigValue());
            //三级推广佣金比例
            Config config7 = new Config();
            config7.setConfigName("THIRD_LEVEL_RATE");
            Config config8 = configDao.selectOneFromRedis(config7);
            if (config8 == null) {
                System.out.println("redis中获取THIRD_LEVEL_RATE对象失败，尝试从数据库中获取");
                config8 = configDao.getByName("THIRD_LEVEL_RATE");
                if (config8 == null) {
                    System.out.println("数据库中获取THIRD_LEVEL_RATE对象失败");
                    return;
                }
            }

            BigDecimal thirdLevelRate = new BigDecimal(config8.getConfigValue());
            //合伙人推广佣金比例
            Config config9 = new Config();
            config9.setConfigName("PARTNER_RATE");
            Config config10 = configDao.selectOneFromRedis(config9);
            if (config10 == null) {
                System.out.println("redis中获取PARTNER_RATE对象失败，尝试从数据库中获取");
                config10 = configDao.getByName("PARTNER_RATE");
                if (config10 == null) {
                    System.out.println("从数据库中获取PARTNER_RATE对象失败");
                    return;
                }
            }

            BigDecimal partnerLevelRate = new BigDecimal(config10.getConfigValue());
            if ((partnerLevelRate.add(firstLevelRate).add(secondLevelRate).add(thirdLevelRate)).compareTo(new BigDecimal("1")) == 1) {
                System.out.println("推广比例之和不能大于1");
                return;
            }

            for (GoodsOrder goodsOrder : goodsOrderList) {

                BigDecimal remainMoney = finish(goodsOrder, firstLevelRate, secondLevelRate, thirdLevelRate, partnerLevelRate);
                if (remainMoney.compareTo(new BigDecimal(0)) != -1) {
                    goodsOrder.setRemainMoney(remainMoney);
                    goodsOrderDao.modify(goodsOrder);
                }


            }
        }
    }
    //分享经济  添加记录
    public BigDecimal finish(GoodsOrder goodsOrder,BigDecimal firstLevelRate,BigDecimal secondLevelRate,BigDecimal thirdLevelRate,BigDecimal partnerLevelRate ){
        BigDecimal remainMoney=new BigDecimal(0);
        if (goodsOrder == null || !goodsOrder.getOrderState().equals(OrderState.Receipt) || goodsOrder.getCode() == null) {
            return remainMoney;
        }

        // 将订单状态设为已完成
        goodsOrder.setFinishTime(DateUtils.addDays(goodsOrder.getReceiptTime(), 14));
        goodsOrder.setOrderState(OrderState.Finish);
        goodsOrderDao.modify(goodsOrder);

        if(!goodsOrder.getSeckill()) {//非秒杀订单 参与分佣
            remainMoney = (goodsOrder.getSalePrice().subtract(goodsOrder.getDdPrice())).multiply(new BigDecimal(goodsOrder.getNum()));
            if (remainMoney.compareTo(new BigDecimal(0)) == -1) {
                return new BigDecimal(0);
            }

            BigDecimal money = remainMoney;//推荐佣金
            BigDecimal firstCommission = money.multiply(firstLevelRate);//一级推荐佣金
            BigDecimal secondCommission = money.multiply(secondLevelRate);//二级推荐佣金
            BigDecimal thirdCommission = money.multiply(thirdLevelRate);//三级推荐佣金
            // BigDecimal partnerCommission=money.multiply(partnerLevelRate);//合伙人推广佣金 月结 此时先扣除
            // remainMoney=money.subtract(partnerCommission);//剩余佣金
            if (remainMoney.compareTo(new BigDecimal(0)) == -1) {
                return new BigDecimal(0);
            }
            Calendar currCalendar = Calendar.getInstance();
            int currYear = currCalendar.get(Calendar.YEAR);
            int currMonth = currCalendar.get(Calendar.MONTH) + 1;
            User firstUser = userDao.getByLowerUserId(goodsOrder.getUserId());
            if (firstUser != null) {  //判断一级推荐用户是否存在
                Account firstAccount = accountDao.getByUserId(firstUser.getId());
                if (firstAccount == null) {//一级推荐用户的资金账户是否存在
                    System.out.println("一级推荐人id:" + firstUser.getId() + "的资金账户不存在或用户无效");
                } else {
                    remainMoney = remainMoney.subtract(firstCommission);
                    //添加佣金记录
                    Commission commissionFirst = new Commission();
                    commissionFirst.setUpperUserId(firstUser.getId());
                    commissionFirst.setUserLevel(firstUser.getUserLevel());
                    commissionFirst.setCommissionRate(firstLevelRate);
                    commissionFirst.setLowerUserId(goodsOrder.getUserId());
                    commissionFirst.setCommissionSource(CommissionSource.Self);
                    commissionFirst.setCommissionType(CommissionType.Sale);
                    commissionFirst.setCreateTime(new Date());
                    commissionFirst.setReferCode(goodsOrder.getCode());
                    commissionFirst.setOrderMoney(money);
                    commissionFirst.setMoney(firstCommission);
                    commissionFirst.setYear(currYear);
                    commissionFirst.setMonth(currMonth);
                    User secondUser = userDao.getByLowerUserId(firstUser.getId());
                    if (secondUser != null) {//判断二级推荐用户是否存在
                        Account secondAccount = accountDao.getByUserId(secondUser.getId());
                        if (secondAccount == null && UserState.Normal.equals(secondUser.getUserState())) {//二级推荐用户的资金账户是否存在
                            System.out.println("二级推荐人id:" + secondUser.getId() + "的资金账户不存在或用户无效");
                        } else {
                            //佣金记录
                            Commission commissionSecond = new Commission();
                            commissionSecond.setUpperUserId(secondUser.getId());
                            commissionSecond.setUserLevel(secondUser.getUserLevel());
                            commissionSecond.setCommissionRate(secondLevelRate);
                            commissionSecond.setLowerUserId(goodsOrder.getUserId());
                            commissionSecond.setCommissionSource(CommissionSource.Lower);
                            commissionSecond.setCommissionType(CommissionType.Sale);
                            commissionSecond.setCreateTime(new Date());
                            commissionSecond.setReferCode(goodsOrder.getCode());
                            commissionSecond.setOrderMoney(money);
                            commissionSecond.setMoney(secondCommission);
                            commissionSecond.setYear(currYear);
                            commissionSecond.setMonth(currMonth);

                            remainMoney = remainMoney.subtract(secondCommission);
                            User thirdUser = userDao.getByLowerUserId(secondUser.getId());
                            if (thirdUser != null) {//判断二级推荐用户是否存在，是否有效
                                Account thirdAccount = accountDao.getByUserId(thirdUser.getId());
                                if (thirdAccount == null) {//三级推荐用户的资金账户是否存在
                                    System.out.println("三级推荐人id:" + thirdUser.getId() + "的资金账户不存在或用户无效");
                                } else {
                                    // 更改用户余额  添加资金流水

                                    remainMoney = remainMoney.subtract(thirdCommission);
                                    //佣金记录
                                    Commission commissionThird = new Commission();
                                    commissionThird.setUpperUserId(thirdUser.getId());
                                    commissionThird.setUserLevel(thirdUser.getUserLevel());
                                    commissionThird.setCommissionRate(thirdLevelRate);
                                    commissionThird.setLowerUserId(goodsOrder.getUserId());
                                    commissionThird.setCommissionSource(CommissionSource.Lowest);
                                    commissionThird.setCommissionType(CommissionType.Sale);
                                    commissionThird.setCreateTime(new Date());
                                    commissionThird.setReferCode(goodsOrder.getCode());
                                    commissionThird.setOrderMoney(money);
                                    commissionThird.setMoney(thirdCommission);
                                    commissionThird.setYear(currYear);
                                    commissionThird.setMonth(currMonth);
                                    coreLogic.addFundsFlow(firstUser.getId(), firstCommission, FlowSource.Commission, FlowType.Add, goodsOrder.getId(), goodsOrder.getCode());
                                    coreLogic.changeMoneyAccount(firstUser.getId(), firstCommission, FlowSource.Commission, FlowType.Add);
                                    coreLogic.addFundsFlow(secondUser.getId(), secondCommission, FlowSource.Commission, FlowType.Add, goodsOrder.getId(), goodsOrder.getCode());
                                    coreLogic.changeMoneyAccount(secondUser.getId(), secondCommission, FlowSource.Commission, FlowType.Add);
                                    coreLogic.addFundsFlow(thirdUser.getId(), thirdCommission, FlowSource.Commission, FlowType.Add, goodsOrder.getId(), goodsOrder.getCode());
                                    coreLogic.changeMoneyAccount(thirdUser.getId(), thirdCommission, FlowSource.Commission, FlowType.Add);
                                    commissionDao.add(commissionFirst);
                                    commissionDao.add(commissionSecond);
                                    commissionDao.add(commissionThird);
                                }
                            } else {
                                coreLogic.addFundsFlow(firstUser.getId(), firstCommission, FlowSource.Commission, FlowType.Add, goodsOrder.getId(), goodsOrder.getCode());
                                coreLogic.changeMoneyAccount(firstUser.getId(), firstCommission, FlowSource.Commission, FlowType.Add);
                                coreLogic.addFundsFlow(secondUser.getId(), secondCommission, FlowSource.Commission, FlowType.Add, goodsOrder.getId(), goodsOrder.getCode());
                                coreLogic.changeMoneyAccount(secondUser.getId(), secondCommission, FlowSource.Commission, FlowType.Add);
                                commissionDao.add(commissionFirst);
                                commissionDao.add(commissionSecond);
                            }
                        }

                    } else {
                        coreLogic.addFundsFlow(firstUser.getId(), firstCommission, FlowSource.Commission, FlowType.Add, goodsOrder.getId(), goodsOrder.getCode());
                        coreLogic.changeMoneyAccount(firstUser.getId(), firstCommission, FlowSource.Commission, FlowType.Add);
                        commissionDao.add(commissionFirst);
                    }
                }
            }
        }
        return remainMoney;
    }

    public void  finishOrderThread(){

        for (DateSourceType dateSourceType: DateSourceType.values()) {
            Thread threadS=  new Thread_v1(dateSourceType);
            threadS.start();
        }

    }
    class  Thread_v1 extends  Thread{
        DateSourceType dateSourceType1;
        Thread_v1(DateSourceType dateSourceType){
            this.dateSourceType1 = dateSourceType;

        }
        public void run() {

            try {
                System.out.println("确认收货14天后订单完成   公司编号:"+dateSourceType1.getIntValue()+"--执行开始");
                DBContextHolder.setDBType(dateSourceType1.toString());
                finishOrder();
                DBContextHolder.clearDBType();
                System.out.println("确认收货14天后订单完成   公司编号:"+dateSourceType1.getIntValue()+"--执行结束");
            }
            catch (Exception e){
                e.printStackTrace();
            }
            finally {
                System.out.println("叮当淘");
            }

        }
    }


}